package net.lulihu.pangolin.headless.server.component;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import net.lulihu.pangolin.headless.common.container.annotation.Autowired;
import net.lulihu.pangolin.headless.common.container.annotation.Component;
import net.lulihu.pangolin.headless.common.container.templet.ApplicationLifeCycle;
import net.lulihu.pangolin.headless.common.protocol.ProtocolMessageDecoder;
import net.lulihu.pangolin.headless.common.protocol.ProtocolMessageEncoder;
import net.lulihu.pangolin.headless.server.config.ProxyServerConfig;
import net.lulihu.pangolin.headless.server.handler.IdleStateCheckHandler;
import net.lulihu.pangolin.headless.server.handler.ProxyServerMessageHandler;

import java.util.concurrent.ExecutionException;

/**
 * 服务代理网络组件
 * <p>
 * 负责和代理客户端的数据交互
 */
@Slf4j
@Component
public class ServerProxyNetworkComponent extends AbstractNetwork implements ApplicationLifeCycle {

    // 代理服务器工作线程组
    private EventLoopGroup serverBossGroup;
    private EventLoopGroup serverWorkGroup;

    @Autowired
    private ProxyServerConfig proxyServerConfig;

    @Override
    public void containerLoadSuccessAfter() {
        this.serverBossGroup = new NioEventLoopGroup();
        this.serverWorkGroup = new NioEventLoopGroup();

        serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(serverBossGroup, serverWorkGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new ProtocolMessageDecoder());
                        pipeline.addLast(new ProtocolMessageEncoder());
                        pipeline.addLast(new IdleStateCheckHandler());
                        pipeline.addLast(new ProxyServerMessageHandler());
                    }
                });

        try {
            Integer bindPort = bindPort(proxyServerConfig.getPort());

            if (log.isInfoEnabled()) log.info("服务器端口：{} 启动...", bindPort);
        } catch (ExecutionException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public void applicationShowdown() {
        log.info("服务代理网络组件关闭ing");

        serverBossGroup.shutdownGracefully();
        serverWorkGroup.shutdownGracefully();
    }

}
